package com.eksframework.commons.core.validator;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.util.Objects;
import java.util.Set;

/**
 * 验证器
 *
 * @author chenfenghai
 * @version: 1.0
 * @date: 2020-12-03 10:36
 */
public class EksValidator {

    /**
     * 验证器
     */
    private static Validator validator = null;

    /**
     * 私有构造方法
     */
    private EksValidator() {

    }

    /**
     * 设置验证器
     *
     * @param value 验证器实现类
     */
    public static void setValidator(Validator value) {
        validator = value;
    }

    /**
     * 获取验证器
     *
     * @return Validator
     */
    private static Validator getValidator() {
        if (Objects.nonNull(validator)) {
            return validator;
        }
        validator = Validation.buildDefaultValidatorFactory().getValidator();
        return validator;
    }

    /**
     * 对参数校验对象使用指定的校验组进行校验
     *
     * @param object 参数校验对象
     * @param groups 校验组
     * @param <T>    校验对象类型
     * @return ValidatorResult
     */
    public static <T> ValidatorResult<T> validate(T object, Class<?>... groups) {
        Objects.requireNonNull(object, "参数校验对象不能为空");
        Set<ConstraintViolation<T>> violations = getValidator().validate(object, groups);
        return new ValidatorResult<>(violations);
    }

    /**
     * 对参数校验对象的指定参数使用指定的校验组进行校验
     *
     * @param object       参数校验对象
     * @param propertyName 属性名
     * @param groups       校验组
     * @param <T>          校验对象类型
     * @return ValidatorResult
     */
    public static <T> ValidatorResult<T> validateProperty(T object, String propertyName, Class<?>... groups) {
        Objects.requireNonNull(object, "参数校验对象不能为空");
        Objects.requireNonNull(propertyName, "参数校验属性名不能为空");
        Set<ConstraintViolation<T>> violations = getValidator().validateProperty(object, propertyName, groups);
        return new ValidatorResult<>(violations);
    }

    /**
     * 对Bean的属性和指定值使用指定的校验组进行校验
     *
     * @param beanType     Bean类型
     * @param propertyName 属性名
     * @param value        校验值
     * @param groups       校验组
     * @param <T>          校验对象类型
     * @return ValidatorResult
     */
    public static <T> ValidatorResult<T> validateValue(
            Class<T> beanType, String propertyName, Object value, Class<?>... groups) {
        Objects.requireNonNull(beanType);
        Objects.requireNonNull(propertyName);
        Objects.requireNonNull(value);
        Set<ConstraintViolation<T>> violations = getValidator().validateValue(
                beanType, propertyName, value, groups);
        return new ValidatorResult<>(violations);
    }
}
